﻿#region Copyright
//       Copyright (c) 2009 - Antoine Jaussoin - http://www.jaussoin.com/blog/
// 
//        This program is free software: you can redistribute it and/or modify
//        it under the terms of the GNU General Public License as published by
//        the Free Software Foundation, either version 3 of the License, or
//        (at your option) any later version.
// 
//        This program is distributed in the hope that it will be useful,
//        but WITHOUT ANY WARRANTY; without even the implied warranty of
//        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//        GNU General Public License for more details.
// 
//        You should have received a copy of the GNU General Public License
//        along with this program.  If not, see <http://www.gnu.org/licenses/>.
#endregion

using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using FT.Architecture.Example.Core.Entities.Cars;
using FT.Architecture.Example.Core.Entities.Humans;
using FT.Architecture.Example.Core.Repositories;
using FT.Architecture.Example.Data.Repositories;
using FT.Architecture.Logging;
using FT.Architecture.NHibernate.Context;
using FT.Architecture.NHibernate.Factories;
using FT.Architecture.NHibernate.Persistence;
using FT.Architecture.NHibernate.Repositories;
using FT.Architecture.NHibernate.SessionManagement;
using FT.Architecture.Utils.Log;
using log4net.Config;

namespace FT.Architecture.Example.Console
{
    public class Program
    {
        
        private static void Main(string[] args)
        {
            XmlConfigurator.Configure();

            //Uncomment this line if the schema was not created yet 
            //(or if you want to drop the existing one and recreate dummy data)
            CreateSchema();

            //Now let's see some example of how to use the code
            //You can make your own if you want!

            var sessionProvider = new SessionProviderService();
            var logService = new LogService(new Log4NetLoggerFactory());
            var unitOfWork = new NHibernateUnitOfWork(sessionProvider, new XmlMappingNHibernateConfigurator());
            unitOfWork.Initialise();
            var manRepository = new NHibernateRepository<Man>(sessionProvider, null, logService);
            var humanRepository = new NHibernateHumanRepository(sessionProvider, null, logService);
            var supermanRepository = new NHibernateRepository<Superman>(sessionProvider, null, logService);
            var carRepository = new NHibernateGenericRepository<ICar, Guid>(sessionProvider, null, logService);
            var persistenceService = new PersistenceService(new XmlMappingNHibernateConfigurator());

            using (unitOfWork.Start())
            {
                persistenceService.UpdatePersistence();
            }

            using (unitOfWork.Start())
            {
                //First example, simple one, we get a random IHuman entity and display
                //properties of it, including properties of other entities

                IHuman human = humanRepository.GetRandom();
                System.Console.Out.WriteLine("My name is " + human.Name);
                if (human.Father != null)
                    System.Console.Out.WriteLine("My father name is " + human.Father.Name);

                //Second example: we display all the humans starting with Ant
                //We can do it in two ways: Linq, or the repository methods

                var humans = from h in humanRepository.GetLinq()
                             where h.Name.StartsWith("Ant")
                             select h;

                var humans2 = humanRepository.GetAllByMember(x => x.Name, "Ant%");

                System.Console.Out.WriteLine("Linq List:");
                foreach (var h in humans)
                    System.Console.Out.WriteLine("\t{0} ({1})", h.Name, h.Id);

                System.Console.Out.WriteLine("Repository List:");
                foreach (var h in humans2)
                    System.Console.Out.WriteLine("\t{0} ({1})", h.Name, h.Id);


                //Third example: we can query any fine-grained class: instead of getting all the 
                //IHuman as a whole, we can only take into account the supermen:

                var supermen = supermanRepository.GetAllByMember(x => x.Name, "D%");
                System.Console.Out.WriteLine("Supermen starting by D:");
                foreach (var h in supermen)
                    System.Console.Out.WriteLine("\t{0} ({1})", h.Name, h.Id);


                //Fourth example: we work with a Guid-based entity

                for (int i = 0; i < 10; i++)
                {
                    var aCar = carRepository.GetRandom();
                    System.Console.Out.WriteLine(aCar.Brand + " of color " + aCar.Colour.ToKnownColor());
                }


                //Your turn now: do what you want!
                //t.

                unitOfWork.Commit();
            }



            System.Console.Out.WriteLine("-- END --");
            System.Console.ReadLine();
        }

        /// <summary>
        /// (re)Create the schema
        /// PLEASE ENSURE YOU HAVE A DATABASE CALLED "ncontrols" FIRST
        /// </summary>
        public static void CreateSchema()
        {
            ////unitOfWork.Start();
            ////    t.GenerateSchema();
            ////    t.Commit();
            ////}

            ////unitOfWork.Start();
            ////    t.GenerateData();
            ////    t.Commit();
            ////}
        }
    }
}